// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// b [author] rhyme_lph
// S [email]  rhymelph@gmail.com
// g [github] https://github.com/rhymelph

import 'dart:async';

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/my_invitations_entity.dart';
import 'package:finance_app/src/entities/user_profile_entity.dart';
import 'package:finance_app/src/http_service/http_invitation_service.dart';
import 'package:finance_app/src/http_service/http_login_service.dart';
import 'package:finance_app/src/http_service/http_user_service.dart';
import 'package:finance_app/src/mixin/validate_code_mixin.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:flutter/material.dart';

class RegisterProvider extends BaseProvider with ValidateCodeMixin {
  TextEditingController phoneController = TextEditingController();
  FocusNode phoneFocus = FocusNode();
  TextEditingController emailController = TextEditingController();
  FocusNode emailFocus = FocusNode();
  TextEditingController validateController = TextEditingController();
  FocusNode validateFocusNode = FocusNode();

  bool enable = false;
  bool isCheckPrivacyPolicy = false;

  String countryCode = "+65";

  String currentType = S.current.email;

  int step = 0;

  bool enableVerify = false;
  String number;

  String hasPhoneError;
  String hasEmailError;

  @override
  Future get dataFuture => null;

  @override
  void dispose() {
    super.dispose();
    phoneController.dispose();
    phoneFocus.dispose();
    emailController.dispose();
    emailFocus.dispose();
    validateController.dispose();
    validateFocusNode.dispose();
  }

  @override
  void initState() {
    super.initState();
    validateController.addListener(_onUpdateValidateInput);
    phoneController.addListener(_onUpdateRegisterInput);
    emailController.addListener(_onUpdateRegisterInput);
  }

  void _onUpdateRegisterInput() {
    if (currentType == S.current.email) {
      if (emailController.text.length > 0) {
        if (enable == false) {
          enable = true;
          update();
        }
      } else {
        if (enable == true) {
          enable = false;
          update();
        }
      }
    } else {
      if (phoneController.text.length > 0) {
        if (enable == false) {
          enable = true;
          update();
        }
      } else {
        if (enable == true) {
          enable = false;
          update();
        }
      }
    }
  }

  void _onUpdateValidateInput() {
    if (validateController.text.length > 0) {
      if (enableVerify == false) {
        enableVerify = true;
        update();
      }
    } else {
      if (enableVerify == true) {
        enableVerify = false;
        update();
      }
    }
  }

  void onNavLogin() {
    //To update ConfigKey.showLogin
    RProvider.myProvider.updateGlobalMap();
    phoneFocus.unfocus();
    Routes.navigateTo(RouterGenProviders.loginPage, clearStack: true);
  }

  void onChangeType(String e) {
    if (currentType == e) return;
    currentType = e;
    _onUpdateRegisterInput();
    update();
  }

  void onRegisterByPhoneNumber() async {
    phoneFocus.unfocus();
    String phoneNumber = phoneController.text;
    if (phoneNumber.length < 8) {
      hasPhoneError = S.current.please_enter_valid_phone_number;
      update();
      return;
    }
    await post(HttpLoginService.loginOtp(countryCode, phoneNumber),
        loadingTip: S.current.loading, onSuccess: (result) {
      step++;
      update();
      number = phoneController.text;
    }, onError: (_, ____, __, ___) {
      hasPhoneError = ____;
      update();
    });
    resetTimer();
  }

  void onRegisterByEmail() async {
    emailFocus.unfocus();
    String email = emailController.text;
    if (email.length < 8) {
      hasEmailError = 'Please enter a valid email address.';
      update();
      return;
    }
    await post(HttpLoginService.loginEmailOtp(email),
        loadingTip: S.current.loading, onSuccess: (result) {
      step++;
      update();
      number = emailController.text;
    }, onError: (_, ____, __, ___) {
      hasEmailError = ____;
      update();
    });
    resetTimer();
  }

  void onChangeCountryCode(value) {
    countryCode = value;
  }

  void onResentOTP() async {
    hasValidateError = false;
    if (currentType == S.current.email) {
      await post(HttpLoginService.loginEmailOtp(number),
          autoHandler: AutoHandler.Toast,
          loadingTip: S.current.loading, onSuccess: (result) {
        showToast(S.current.resent_success);
        resetTimer();
        update();
      });
    } else {
      final phone = getPhone(number);
      await post(HttpLoginService.loginOtp(countryCode, phone),
          autoHandler: AutoHandler.Toast,
          loadingTip: S.current.loading, onSuccess: (result) {
        showToast(S.current.resent_success);
        resetTimer();
        update();
      });
    }
  }

  void onVerify() async {
    bool isEmail = currentType == S.current.email;

    validateFocusNode.unfocus();
    String text = validateController.text;
    obtainContext?.call((context) async {
      bool isSuccess = false;
      BaseConfig.dialogBase
          .showLoadingDialog(context: context, text: S.current.loading);
      if (isEmail) {
        await post(HttpLoginService.otpCheckEmailRegister(number, text),
            onSuccess: (result) {
          isSuccess = true;
        }, onError: (_, ____, __, ___) {
          hasValidateError = true;
          update();
        });
      } else {
        await post(
            HttpLoginService.otpCheckRegister(
                countryCode, getPhone(number), text), onSuccess: (result) {
          isSuccess = true;
        }, onError: (_, ____, __, ___) {
          hasValidateError = true;
          update();
        });
      }

      if (!isSuccess) {
        Navigator.of(context).pop();
        return;
      }
      isSuccess = false;
      if (isEmail) {
        await post(HttpLoginService.registerByEmail(number, text),
            onSuccess: (result) async {
          isSuccess = true;
          RProvider.myProvider.globalMap[ConfigKey.token] =
              result.data[BaseConfig.presenterBase.dataKey]['token'];
          await RProvider.myProvider.updateGlobalMap();
        }, onError: (_, ____, __, ___) {
          hasValidateError = true;
          update();
        });
      } else {
        await post(
            HttpLoginService.register(countryCode, getPhone(number), text),
            onSuccess: (result) async {
          isSuccess = true;
          RProvider.myProvider.globalMap[ConfigKey.token] =
              result.data[BaseConfig.presenterBase.dataKey]['token'];
          await RProvider.myProvider.updateGlobalMap();
        }, onError: (_, ____, __, ___) {
          hasValidateError = true;
          update();
        });
      }

      if (isSuccess) {
        //获取邀请
        await post(HttpInvitationService.myInvitation(),
            autoHandler: AutoHandler.Toast, onSuccess: (result) async {
          RProvider.myProvider.globalMap[ConfigKey.myInvitations] =
              getEntityFromResult<List<MyInvitationsEntity>>(result);
          if (Config.myInvitations.length == 0) {
            RProvider.myProvider.globalMap[ConfigKey.myInvitations] = null;
          }
          await RProvider.myProvider.updateGlobalMap();
        });
        //获取用户信息
        await post(HttpUserService.getMyProfile(),
            autoHandler: AutoHandler.Toast, onSuccess: (result) async {
          RProvider.myProvider.globalMap[ConfigKey.userProfile] =
              getEntityFromResult<UserProfileEntity>(result);
          await RProvider.myProvider.updateGlobalMap();
        });
        if (Config.myInvitations != null) {
          Routes.navigateTo(RouterGenProviders.pendingInvitationPage,
              clearStack: true);
        } else if (Config.userProfile.name == null) {
          Routes.navigateTo(RouterGenProviders.createAccountPage,
              clearStack: true);
        } else {
          Routes.navigateTo(RouterGenProviders.dashboardPage, clearStack: true);
        }
      } else {
        Navigator.of(context).pop();
      }
    });
  }

  String getPhone(String phoneText) {
    String phoneNumber = phoneText.replaceAll(' ', '');
    return phoneNumber;
  }

  void onChangePrivacyCheck() {
    FocusManager.instance.primaryFocus.unfocus();
    isCheckPrivacyPolicy = !isCheckPrivacyPolicy;
    update();
  }
}
